////////////////////////////////////////////////////////////////////////////////
//
//  ObjectStorage.h
//
//  A container class that will hold all objects that are read from IRIT file.
//  It's made singleton in order to avoid using a global container that is
//  otherwise needed to be accessible from both the callback IRIT parser
//  function and the scene rendering functions.
//
////////////////////////////////////////////////////////////////////////////////
#ifndef OBJECT_STORAGE_H
#define OBJECT_STORAGE_H

#include "PolyObject.h"
#include "MinMaxBox.h"
#include <WinDef.h>

#include <vector>
using std::vector;


class ObjectStorage : public MinMaxBox
{
	public:
		static ObjectStorage& getInstance    ( );
        vector<PolyObject>&   getAllObjects  ( );
		void                  addObject      ( PolyObject objectPtr );
		void                  clear          ( );
		void				  drawBoundingBox( ) const;
        void                  enableColor    ( );
        void                  disableColor   ( );

    private:
        vector<PolyObject>  objects;
        // making it singleton
		                    ObjectStorage( ) { }
                            ~ObjectStorage( );
		                    ObjectStorage( ObjectStorage& instance ) { }
		void                operator=    ( ObjectStorage& instance ) { }
};


inline ObjectStorage::~ObjectStorage( )
{
    clear( );
}


inline ObjectStorage& ObjectStorage::getInstance( )
{
    static ObjectStorage instance;
    return instance;
}


inline vector<PolyObject>& ObjectStorage::getAllObjects( )
{
    return objects;
}


inline void ObjectStorage::drawBoundingBox( ) const
{
    GLubyte bbIndices[24] =
      { 0, 3, 7, 4,
        1, 5, 6, 2,
        0, 1, 2, 3,
        4, 7, 6, 5,
        0, 4, 5, 1,
        3, 2, 6, 7 };

    GLfloat xMin = this->getMinX( ),
            xMax = this->getMaxX( ),
            yMin = this->getMinY( ),
            yMax = this->getMaxY( ),
            zMin = this->getMinZ( ),
            zMax = this->getMaxZ( );

    GLfloat bbMargin = ( max( xMax, max( yMax, zMax ) ) -
                         min( xMin, min( yMin, zMin ) ) ) / 1000;

    xMin -= bbMargin;
    xMax += bbMargin;
    yMin -= bbMargin;
    yMax += bbMargin;
    zMin -= bbMargin;
    zMax += bbMargin;

    GLfloat bbVertices[24] =
      { xMin, yMin, zMin,
        xMax, yMin, zMin,
        xMax, yMin, zMax,
        xMin, yMin, zMax,
        xMin, yMax, zMin,
        xMax, yMax, zMin,
        xMax, yMax, zMax,
        xMin, yMax, zMax };

    GLint mode[2] = {0};  // probably no need for two integers, but not sure

    glGetIntegerv( GL_POLYGON_MODE, mode );           // save mode
    glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );

    glEnableClientState( GL_VERTEX_ARRAY );
    glVertexPointer( 3, GL_FLOAT, 0, bbVertices );
    glDrawElements( GL_QUADS, 24, GL_UNSIGNED_BYTE, bbIndices );
    glDisableClientState( GL_VERTEX_ARRAY );

    glPolygonMode( GL_FRONT_AND_BACK, mode[0] );      // restore mode
}


inline void ObjectStorage::addObject(PolyObject objectPtr)
{
	this->setMaxX( max( objectPtr.getMaxX( ), this->getMaxX( ) ) );
	this->setMaxY( max( objectPtr.getMaxY( ), this->getMaxY( ) ) );
	this->setMaxZ( max( objectPtr.getMaxZ( ), this->getMaxZ( ) ) );

	this->setMinX( min( objectPtr.getMinX( ), this->getMinX( ) ) );
	this->setMinY( min( objectPtr.getMinY( ), this->getMinY( ) ) );
	this->setMinZ( min( objectPtr.getMinZ( ), this->getMinZ( ) ) );

    objects.push_back(objectPtr);
}


inline void ObjectStorage::clear()
{
    resetMinMaxXYZ();
    objects.clear();
}


inline void ObjectStorage::enableColor( )
{
    for ( vector<PolyObject>::iterator it = ObjectStorage::getInstance( ).getAllObjects( ).begin( );
        it != ObjectStorage::getInstance( ).getAllObjects( ).end( );
        ++it )
    {
        it->enableColor( );
    }
}


inline void ObjectStorage::disableColor( )
{
    for ( vector<PolyObject>::iterator it = ObjectStorage::getInstance( ).getAllObjects( ).begin( );
        it != ObjectStorage::getInstance( ).getAllObjects( ).end( );
        ++it )
    {
        it->disableColor( );
    }
}

#endif // OBJECT_STORAGE_H

// EOF /////////////////////////////////////////////////////////////////////////